package cn.keniykey.mc.viewlibrary.reflection;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.annotation.Nullable;

import cn.keniykey.mc.viewlibrary.ViewLibraryMain;

/**
 * 反射方法
 */
public final class ReflectionMethod{
	private final Method method;
	
    public ReflectionMethod(final Method method) {
        this.method = method;
        method.setAccessible(true);
    }
    
    public Method getMethod() {
        return this.method;
    }
    public Class<?> getDeclaringClass() {
    	return this.method.getDeclaringClass();
    }
    public Class<?> getReturnClass() {
    	return this.method.getReturnType();
    }
    public int getArgumentsCount() {
        return this.method.getParameterTypes().length;
    }
    /**
     * 动态方法调用（自行缓存）
     */
    public ReflectionDynamicMethod getDynamicMethod(final Object obj) {
        return new ReflectionDynamicMethod(this.method, obj);
    }
    @Nullable
    public Object dynamicInvoke(final Object obj, final Object...params) {
    	try {
    		return this.method.invoke(obj, params);
    	}catch(Exception ex) {
    		throw new RuntimeException(ex);
    	}
    }
    /**
     * 静态方法调用
     */
    @Nullable
    public Object invoke(final Object... params) {
        try {
            return this.method.invoke(null, params);
        }catch (Exception ex) {
        	throw new RuntimeException(ex);
        }
    }
    
	public void showLogger() {
		final Logger logger = ViewLibraryMain.getPlugin().getLogger();
		logger.warning("---------------" + this.method.getName() + "--------------------");
		int index = 0;
		final Type[] parametertypes = method.getGenericParameterTypes();
		for(Type par_type : parametertypes) {
			final StringBuilder strb = new StringBuilder("method_par_");
			strb.append(++index).append(": ");
			final Object obj_par = ReflectionGenericClass.getParameterClasses(par_type);
			if(obj_par instanceof Class) {
				strb.append("[Class]");
				final Class<?> clazz_par = (Class<?>)obj_par;
				strb.append(clazz_par.getName());
			}else if(obj_par instanceof LinkedList) {
				strb.append("[LinkedList]");
				@SuppressWarnings("unchecked")
				final LinkedList<Class<?>> linke_clazz_par = (LinkedList<Class<?>>) obj_par;
				strb.append("<C>");
				strb.append(linke_clazz_par.removeFirst().getName());
				for(Class<?> linked_clazz : linke_clazz_par) {
					strb.append(", [G]").append(linked_clazz.getName());
				}
			}
			logger.warning(strb.toString());
		}
		logger.warning("------------------end-------------------------");
	}
}